#include "dbg/dbg.h"
#include <iostream>

class ProductA
{
public:
    virtual ~ProductA() {}
    virtual const char *getName() = 0;
};

class ConcreteProductAX : public ProductA
{
public:
    ~ConcreteProductAX() {}
    const char *getName()
    {
        return "A-X";
    }
};

class ConcreteProductAY : public ProductA
{
public:
    ~ConcreteProductAY() {}
    const char *getName()
    {
        return "A-Y";
    }
};

class ProductB
{
public:
    virtual ~ProductB() {}
    virtual const char *getName() = 0;
};

class ConcreteProductBX : public ProductB
{
public:
    ~ConcreteProductBX() {}
    const char *getName()
    {
        return "B-X";
    }
};

class ConcreteProductBY : public ProductB
{
public:
    ~ConcreteProductBY() {}
    const char *getName()
    {
        return "B-Y";
    }
};

class AbstractFactory
{
public:
    ~AbstractFactory() {}

    virtual ProductA *createProductA() = 0;
    virtual ProductB *createProductB() = 0;
};

class ConcreteFactoryX : public AbstractFactory
{
public:
    ~ConcreteFactoryX() {}

    ProductA *createProductA()
    {
        return new ConcreteProductAX();
    }

    ProductB *createProductB()
    {
        return new ConcreteProductBX();
    }
};

class ConcreteFactoryY : public AbstractFactory
{
public:
    ~ConcreteFactoryY() {}

    ProductA *createProductA()
    {
        return new ConcreteProductAY();
    }

    ProductB *createProductB()
    {
        return new ConcreteProductBY();
    }
};

int main()
{
    dbg("Hello, world");

    ConcreteFactoryX factoryX;
    ConcreteFactoryY factoryY;

    ProductA *pa1 = factoryX.createProductA();
    std::cout << "factoryX.createProductA: " << pa1->getName() << std::endl;

    ProductA *pa2 = factoryY.createProductA();
    std::cout << "factoryY.createProductA: " << pa2->getName() << std::endl;

    delete pa1;
    delete pa2;

    return 0;
}